import sys
sys.path.append('.') # allow to find modules 'here'

# ----------------------------------------------------
import wx
import wx.aui
import wx.py 
import wx.glcanvas
import wx.lib.flatnotebook as fnb
import math

from types import *
from demoEnginePython import *

#---------------------------------------------------------------------------
def time():
    return viewer.Time()/1000.0

#---------------------------------------------------------------------------

# nel modo con il tempo esplicito 
# lo start_time e' uguale per tutti 
# e allora lo deve detrarre l'anim-manager

# facciamo che man mano che le action 
# expirano AM li toglie dalla coda
# cosi non deve fare il for per 
# controllare quando sono expired tutti

#---------------------------------------------------------------------------
class Wait:
    def __init__(self, len):
        self.len = len
        am.add(self)

    def tick( self, time ):
        if( time >= self.len ):
            am.set_expired(self)
#---------------------------------------------------------------------------
class Call:
    def __init__(self, do_time, callback, args):
        self.do_time = do_time
        self.callback = callback
        self.args = args
        am.add(self)

    def tick( self, time ):
        if( time >= self.do_time ):
            self.callback(self.args)
            am.set_expired(self)
#---------------------------------------------------------------------------
class Anim:
    def __init__(self, start_time, len, callback, v1, v2 ):
        self.start_time = start_time * 1.0
        self.len = len
        self.end_time = start_time+len
        self.v1 = v1
        self.v2 = v2
        self.callback = callback
        am.add(self)
        globals()['T'] = self.end_time

    def tick(self, time):
        if( time <  self.start_time ): return
        if( time >= self.end_time ):
            am.set_expired(self)
            t = 1
        else:
            t = (time-self.start_time)/self.len
            t = 0.5 * (1 + math.sin( 3.14159265 * (t-0.5) ))
        v = self.interpolate( self.v1,self.v2,t )
        self.callback(v)

    def interpolate(self, v1,v2,t):
        if type(v1) is FloatType or type(v1) is IntType:
            return v1*(1-t)+v2*t
        else:
            return v1.Mul(1-t).Sum(v2.Mul(t) )
        
#---------------------------------------------------------------------------
class AnimManager:
    def __init__(self):
        self.clear()
    
    def clear(self):
        self.all_actions = []
        self.running_actions = []
        self.loopmode = False
        self.running = False
        globals()['T'] = 0
   
    def add(self, action):
        self.all_actions.append(action)

    def play(self):
        self.loopmode = False
        self._start()

    def loop(self):
        self.loopmode = True
        self._start()

    def _start(self):
        self.running_actions = []
        for a in self.all_actions:
            self.running_actions.append(a)
        self.start_time = time()
        self.running = True

    def stop(self):
        self.running = False
        self.loopmode = False
        
    def tick(self):
        if not self.running : return

        t = time() - self.start_time
        lst = []
        for a in self.running_actions:
            lst.append(a)
        for a in lst:
            a.tick(t)
        if len(self.running_actions ) == 0:
            if self.loopmode:
                self.loop()
            else:
                self.stop()
                
    def set_expired(self,action):
        self.running_actions.remove(action)
        
#---------------------------------------------------------------------------

class TestFrame(wx.Frame):
    def __init__(self, parent=None, ID=-1, title='pyOSG' ):
        wx.Frame.__init__(self, parent, ID, title)
        
        #-- shell---------------------------------------------
        self.shell = wx.py.shell.Shell(self, -1, introText="",style =wx.NO_BORDER)

        #-- shell---------------------------------------------
        self.MakeControlPanel()

        # --- OSG ---------------------------------
        self.am = AnimManager()

        self.viewerPanel = wx.glcanvas.GLCanvas(self,-1)
        self.viewer = Viewer( self.viewerPanel.GetHandle() )

        globals()['am'] = self.am
        globals()['viewer'] = self.viewer
        #globals()['cam'] = self.viewer.GetCamera()
        globals()['cm'] = self.viewer.GetManipulator()
        
        self.root = Node()
        print self.root.Load("axes.osg")
        self.viewer.SetRoot(self.root)

        #self.node = Node(self.root)
        #self.node.Scale(0.1)
        #print self.node.Load("cow.osg")        
        #a=Animation( 0,1,Vec(0,0,0),Vec(5,0,0), self.node.SetPosition)
        #self.am.add( a )

        #globals()['r'] = self.root
        #globals()['n'] = self.node 

        # --- Timer ---------------------------------
        self.timer = wx.Timer(self,-1)
        #self.timer.Start(10) 

        # --- Layout ---------------------------------
        self.SetSize(wx.Size(600,600))
        self._mgr = wx.aui.FrameManager()
        self._mgr.SetManagedWindow(self)
        self._mgr.GetArtProvider().SetColor(wx.aui.AUI_ART_INACTIVE_CAPTION_COLOUR, wx.Color(0,150,255)) 
        self._mgr.GetArtProvider().SetColor(wx.aui.AUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR, wx.Color(0,80,255)) 
        self._mgr.GetArtProvider().SetColor(wx.aui.AUI_ART_INACTIVE_CAPTION_COLOUR, wx.Color(80,150,255)) 
        self._mgr.GetArtProvider().SetColor(wx.aui.AUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR, wx.Color(80,150,255)) 

        self._mgr.AddPane(self.viewerPanel, wx.aui.PaneInfo().
                        Name("CenterPane").CenterPane())

        self._mgr.AddPane(self.shell, wx.aui.PaneInfo().CaptionVisible(False).
                        Name("shell").Caption("shell").Bottom().
                        BestSize(wx.Size(200,200)).MinSize(wx.Size(200,10)))
        
        self._mgr.AddPane(self.cp, wx.aui.PaneInfo().Fixed().CaptionVisible(False).
                        Name("controls").Caption("controls").Right().
                        BestSize(wx.Size(70,100)).MinSize(wx.Size(70,100)))

        self._mgr.Update()

        # --- Bindings ---------------------------------
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_TIMER, self.OnTimer, id=self.timer.GetId() )
                
    def OnClose(self, event):
        #self.viewer.setSceneData(None)
        self.timer.Stop()
        self.node = None
        self.viewer = None
        self.Destroy()
        
    def OnTimer(self,e):
        self.am.tick()
        self.viewer.Frame()
        
    def MakeControlPanel(self):
        bw = 70
        self.cp = wx.Panel(self,-1)
        self.cpsz = sz = wx.BoxSizer( wx.VERTICAL )
   
        b = wx.Button(self.cp, -1, "Load", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnLoad, b)
        sz.Add(b)
        
        b = wx.Button(self.cp, -1, "Shell", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnConsole, b)
        sz.Add(b)

        b = wx.StaticText(self.cp, -1, " ", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnStop, b)
        sz.Add(b)

        b = wx.Button(self.cp, -1, "Play", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnPlay, b)
        sz.Add(b)

        b = wx.Button(self.cp, -1, "Loop", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnLoop, b)
        sz.Add(b)

        b = wx.Button(self.cp, -1, "Stop", wx.DefaultPosition, wx.Size(bw,-1) )
        self.Bind(wx.EVT_BUTTON, self.OnStop, b)
        sz.Add(b)

        b = wx.StaticText(self.cp, -1, "", wx.DefaultPosition, wx.Size(bw,-1) )
        sz.Add(b)
        b = wx.StaticText(self.cp, -1, " slides:", wx.DefaultPosition, wx.Size(bw,-1) )
        sz.Add(b)

        self.lb = wx.ListBox(self.cp,-1, wx.DefaultPosition, wx.Size(bw,-1))
        self.Bind(wx.EVT_LISTBOX, self.OnSlide, self.lb)
        sz.Add(self.lb)
        
        self.cp.SetSizer(sz)
        sz.Fit(self.cp)        

    def UpdateSlideButtons(self):
        sz = wx.Size(70,len(slides)*16)
        self.lb.Clear()
        for sd in slides:
            self.lb.Append(sd[0])
        self.lb.SetSize(sz)
        self.lb.SetMinSize(sz)
        self.lb.SetMaxSize(sz)
        self.lb.SetBestFittingSize(sz)
        self.cpsz.Fit(self.cp)

    def OnLoad(self,e):
        self.timer.Stop()        
        execfile('Slides.py',globals(),globals())
        self.UpdateSlideButtons()
        self.timer.Start(10)        

    def OnPlay(self,e):
        self.am.play()
        
    def OnLoop(self,e):
        self.am.loop()

    def OnStop(self,e):
        self.am.stop()

    def OnConsole(self,e):
        p = self._mgr.GetPane(self.shell)
        if p.IsShown(): 
            p.Hide() 
        else: 
            p.Show()
        self._mgr.Update()
            
    def OnSlide(self,e):
        s = self.lb.GetSelection()
        slides[s][1]()


#---------------------------------------------------------------------------

class TestApp(wx.App):
    def OnInit(self):
        self.frame = TestFrame()
        self.SetTopWindow(self.frame)
        self.frame.OnLoad(0) 
        self.frame.Show() 
        return True
   
#---------------------------------------------------------------------------

if __name__ == '__main__':
    app = TestApp(0)
    app.MainLoop()
    
    

